package com.pug.service.user;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pug.anno.log.PugMQMessage;
import com.pug.anno.log.PugMessage;
import com.pug.bo.KssUserBo;
import com.pug.constant.PugContants;
import com.pug.entity.KssUser;
import com.pug.event.MongoEvent;
import com.pug.idwork.IdWorkService;
import com.pug.localcache.EhCacheService;
import com.pug.mapper.user.UserMapper;
import com.pug.redis.PugRedisOperator;
import com.pug.result.ex.KsdBusinessException;
import com.pug.service.weixin.WeixinData;
import com.pug.utils.FastJsonUtil;
import com.pug.utils.fn.asserts.Vsserts;
import com.pug.vo.KssUserVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.UUID;

/**
 * @author 飞哥
 * @Title: 学相伴出品
 * @Description: 飞哥B站地址：https://space.bilibili.com/490711252
 * 记得关注和三连哦！
 * @Description: 我们有一个学习网站：https://www.kuangstudy.com
 * @date 2022/3/16$ 23:42$
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, KssUser> implements IUserService, PugContants {

    @Autowired
    private EhCacheService ehCacheService;
    @Autowired
    private IdWorkService idWorkService;
    @Autowired
    private PugRedisOperator redisOperator;


    @Override
    @Transactional
    @PugMessage(eventClasses = MongoEvent.class)
    public KssUserBo loginRegSms(KssUserVo kssUser) {
        // 1: 接受用户提交用户手机和短信
        String inputPhone = kssUser.getPhone();
        String inputSmsCode = kssUser.getSmscode();
        // 2: 获取redis缓存中的存储短信
        String cacheSmsCode = redisOperator.get(PUG_XQ_LOGIN_SMS_CODE + inputPhone);
        Vsserts.isEmptyEx(cacheSmsCode, "短信已经失效");
        // 3: 对比短信码是否正确
        if (!cacheSmsCode.equalsIgnoreCase(inputSmsCode)) {
            throw new KsdBusinessException(602, "你输入短信证码有误!");
        }
        // 4：开始进行业务的处理
        KssUser dbUser = this.getByPhone(inputPhone);
        // 如果dbUser，说明没有注册
        if (Vsserts.isNull(dbUser)) {
            // 开始注册
            dbUser = new KssUser();
            dbUser.setPhone(inputPhone);
            dbUser.setIdcode(idWorkService.nextShort());
            dbUser.setNickname("小伴");
            dbUser.setPassword("");
            dbUser.setAvatar("http://122.152.205.72:88/group1/M00/00/05/CpoxxF6ZUySASMbOAABBAXhjY0Y649.png");
            dbUser.setSex(2);
            dbUser.setCountry("中国");
            dbUser.setProvince("");
            dbUser.setCity("");
            dbUser.setIsdelete(0);
            dbUser.setDistrict("");
            dbUser.setDescription("Ta什么都没有留下...");
            dbUser.setBgImg("biimg.jpg");
            dbUser.setStatus(1);
            this.saveOrUpdate(dbUser);

            // 回填信息 用于消息
            kssUser.setNickname(dbUser.getNickname());
            kssUser.setAvatar(dbUser.getAvatar());
            kssUser.setId(dbUser.getId() + "");
        }

        // 5: 存在就返回
        KssUserBo kssUserBo = new KssUserBo();
        BeanUtils.copyProperties(dbUser, kssUserBo);
        // 6: 生成一个uuid代表token
        String tokenUuid = UUID.randomUUID().toString();
        kssUserBo.setToken(tokenUuid);
        // 7 : 登录成功以后，把用户信息放入到缓存中，只要是为了后续业务的需要，
        redisOperator.set(PUG_XQ_LOGIN_USER_INFO + kssUserBo.getId(), FastJsonUtil.toJSON(dbUser));
        // token放入缓存中去，是给同一个用户在不同的端登录。前面登录会自动全部拦截下线。只有最后一次登录的才有效。
        redisOperator.set(PUG_XQ_LOGIN_USER_TOKEN + kssUserBo.getId(), tokenUuid);
        // 8：而且短信码一定注册成功其实也没有任何用处，会占用redis内存空间，所有删除掉
        redisOperator.del(PUG_XQ_LOGIN_SMS_CODE + inputPhone);

        // 本地缓存
        ehCacheService.setCache(PUG_XQ_LOGIN_USER_INFO + kssUserBo.getId(), dbUser);
        ehCacheService.setCache(PUG_XQ_LOGIN_USER_TOKEN + kssUserBo.getId(), tokenUuid);


        return kssUserBo;
    }


    @Override
    @Transactional
    @PugMessage(eventClasses = MongoEvent.class)
    @PugMQMessage(routingkey = "user.mongo.message")
    public KssUserBo loginRegsiterWeixin(WeixinData weixinData){
        // 4：开始进行业务的处理
        KssUser dbUser = this.getByOpenId(weixinData.getOpenid());
        // 如果dbUser，说明没有注册
        if (Vsserts.isNull(dbUser)) {
            // 开始注册
            dbUser = new KssUser();
            dbUser.setOpenid(weixinData.getOpenid());
            dbUser.setUnionid(weixinData.getUnionid());
            dbUser.setPhone(weixinData.getPhonenumber());
            dbUser.setIdcode(idWorkService.nextShort());
            dbUser.setNickname("小伴");
            dbUser.setPassword("");
            dbUser.setAvatar("http://122.152.205.72:88/group1/M00/00/05/CpoxxF6ZUySASMbOAABBAXhjY0Y649.png");
            dbUser.setSex(2);
            dbUser.setCountry("中国");
            dbUser.setProvince("");
            dbUser.setCity("");
            dbUser.setIsdelete(0);
            dbUser.setDistrict("");
            dbUser.setDescription("Ta什么都没有留下...");
            dbUser.setBgImg("http://39.105.38.113:9000/abc/2110058DPP1ZPKKP/1633406083.jpg");
            dbUser.setStatus(1);
            this.saveOrUpdate(dbUser);

            // 回填信息 用于消息
            weixinData.setNickName(dbUser.getNickname());
            weixinData.setAvatarUrl(dbUser.getAvatar());
            weixinData.setUserid(dbUser.getId());
        }

        // 5: 存在就返回
        KssUserBo kssUserBo = new KssUserBo();
        BeanUtils.copyProperties(dbUser, kssUserBo);
        // 6: 生成一个uuid代表token
        String tokenUuid = UUID.randomUUID().toString();
        kssUserBo.setToken(tokenUuid);
        kssUserBo.setSessionkey(weixinData.getSessionkey());
        kssUserBo.setOpenid(weixinData.getOpenid());
        kssUserBo.setUnionid(weixinData.getUnionid());
        // 7 : 登录成功以后，把用户信息放入到缓存中，只要是为了后续业务的需要，
        redisOperator.set(PUG_XQ_LOGIN_USER_INFO + kssUserBo.getId(), FastJsonUtil.toJSON(dbUser));
        // token放入缓存中去，是给同一个用户在不同的端登录。前面登录会自动全部拦截下线。只有最后一次登录的才有效。
        redisOperator.set(PUG_XQ_LOGIN_USER_TOKEN + kssUserBo.getId(), tokenUuid);
        // 本地缓存
        ehCacheService.setCache(PUG_XQ_LOGIN_USER_INFO + kssUserBo.getId(), dbUser);
        ehCacheService.setCache(PUG_XQ_LOGIN_USER_TOKEN + kssUserBo.getId(), tokenUuid);



        return kssUserBo;
    }


    /**
     * 根据用户手机号码查询用户
     *
     * @param phone
     * @return
     */
    @Override
    public KssUser getByPhone(String phone) {
        LambdaQueryWrapper<KssUser> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(KssUser::getPhone, phone);
        return this.getOne(lambdaQueryWrapper);
    }


    /**
     * 根据openid判断是否注册
     *
     * @param openid
     * @return
     */
    @Override
    public KssUser getByOpenId(String openid) {
        LambdaQueryWrapper<KssUser> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(KssUser::getOpenid, openid);
        return this.getOne(lambdaQueryWrapper);
    }
}
